﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace ContinuumSL.Classes
{
    public enum ActivityTypeEnum { Actor, FundReconcile };

    public class Activity
    {
        private DateTime _ActivityDate;
        [Description("Date the Activity Occurrs")]
        public DateTime ActivityDate { get { return _ActivityDate; } set { _ActivityDate = value; } }

        private ActivityTypeEnum _ActivityType;
        [Description("The type of activity")]
        public ActivityTypeEnum ActivityType { get { return _ActivityType; } set { _ActivityType = value; } }

        private Actor _AffectingActor = null;
        [Description("The Affecting Actor")]
        public Actor AffectingActor { get { return _AffectingActor; } set { _AffectingActor = value; } }

        private Fund _AffectingFund = null;
        [Description("The Affecting Fund")]
        public Fund AffectingFund { get { return _AffectingFund; } set { _AffectingFund = value; } }

        private Balance _RenderedBalancePrimary = null;
        [Description("Stores the Rendered Balance")]
        public Balance RenderedBalancePrimary { get { return _RenderedBalancePrimary; } set { _RenderedBalancePrimary = value; } }

        private Balance _RenderedBalanceSecondary = null;
        [Description("Stores the Secondary Rendered Balance (if applicable)")]
        public Balance RenderedBalanceSecondary { get { return _RenderedBalanceSecondary; } set { _RenderedBalanceSecondary = value; } }

        #region Constructors

        public Activity()
        {
        }

        public Activity(DateTime ActivityDate, ActivityTypeEnum ActivityType, Fund AffectingFund)
        {
            this.ActivityDate = ActivityDate;
            this.ActivityType = ActivityType;
            this.AffectingActor = null;
            this.AffectingFund = AffectingFund;
        }

        public Activity(DateTime ActivityDate, ActivityTypeEnum ActivityType, Fund AffectingFund, Balance RenderedBalancePrimary)
        {
            this.ActivityDate = ActivityDate;
            this.ActivityType = ActivityType;
            this.AffectingActor = null;
            this.AffectingFund = AffectingFund;
            this.RenderedBalancePrimary = RenderedBalancePrimary;
        }

        public Activity(DateTime ActivityDate, ActivityTypeEnum ActivityType, Actor AffectingActor)
        {
            this.ActivityDate = ActivityDate;
            this.ActivityType = ActivityType;
            this.AffectingActor = AffectingActor;
            this.AffectingFund = null;
        }

        #endregion

        public override string ToString()
        {
            if (ActivityType == ActivityTypeEnum.Actor)
            {
                return ActivityDate.ToShortDateString() + " Actor:" + AffectingActor.ActorName;
            }

            if (ActivityType == ActivityTypeEnum.FundReconcile)
            {
                return ActivityDate.ToShortDateString() + " Reconcile:" + AffectingFund.Name;
            }

            return "";
        }

        public void Execute()
        {
            switch (ActivityType)
            {
                case ActivityTypeEnum.Actor: AffectingActor.ExecuteActivity(this); break;
                case ActivityTypeEnum.FundReconcile: AffectingFund.ExecuteActivity(this); break;
                default: throw (new Exception("Unknown Activity Type"));
            }
        }

        public bool DoesAffectFund(Fund fund)
        {
            if (ActivityType == ActivityTypeEnum.FundReconcile)
            {
                if (AffectingFund == fund) return true;
            }

            if (ActivityType == ActivityTypeEnum.Actor)
            {
                if (AffectingActor.ActorFundPrimary == fund.Name) return true;
                if (AffectingActor.ActorFundSecondary == fund.Name) return true;
            }

            return false;
        }

    }

    public class ActivityComparer : IComparer<Activity>
    {
        // Attempting to resolve issue where activities on the same day yield different results 
        // Policy i am going to pursue is that Historical Points will always be the last execute
        // This will avoid anomalies in sorting behavior causing variations from projection to projection
        // If you add a historical point you are responsible for making sure any actor activity on that
        // date can be thrown away, otherwise shift your HP or actor dates.

        public int Compare(Activity activity1, Activity activity2)
        {
            if (activity1.ActivityDate != activity2.ActivityDate) 
              return activity1.ActivityDate.CompareTo(activity2.ActivityDate);

            if (activity1.ActivityType == activity2.ActivityType) return 0;
            if (activity1.ActivityType == ActivityTypeEnum.Actor) return -1;
            return 1;
        }

    }
}



